package org.ns.socket.client;

public class ByteBuffer {

    public ByteBuffer(int capacity) {
        this.capacity = capacity;
        values = new byte[capacity];
    }

    public ByteBuffer() {
        values = new byte[capacity];
    }

    int capacity = 1024;
    byte[] values;
    int writeIndex;
    int readIndex;
    int makeWriteIndex = -1;
    int makeReadIndex = -1;

    public void put(int b) {
        if (writeIndex == values.length) {
            int leftindex = readIndex;
            if (makeReadIndex != -1) {
                leftindex = makeReadIndex;
                this.makeReadIndex = 0;
            }
            int length = writeIndex - leftindex;
            byte[] nvalues = new byte[length + 1024];
            System.arraycopy(values, leftindex, nvalues, 0, length);
            readIndex = readIndex - leftindex;
            writeIndex = writeIndex - leftindex;
            if (makeWriteIndex != -1) {
                makeWriteIndex = makeWriteIndex - leftindex;
            }
            this.values = nvalues;
        }
        values[writeIndex ++] = (byte) b;
    }
    public int read() {
        if (readIndex == writeIndex) {
            throw new ArrayIndexOutOfBoundsException("越界了");
        }
        return values[readIndex++];
    }

    public void write(byte[] buf) {
        for (byte b : buf) {
            put(b);
        }
    }
    public void write(byte[] buf, int off, int len) {
        for (int i = 0; i < len; i++, off++) {
            put(buf[off]);
        }
    }

    public int read(byte[] buf) {

        int length = readable();
        if (length == 0) {
            return 0;
        }

        if (length >= buf.length) {
            System.arraycopy(values, readIndex, buf,0,  buf.length);
            readIndex = readIndex + buf.length;
            return buf.length;
        } else {
            System.arraycopy(values, readIndex, buf,0,  length);
            readIndex = readIndex + length;
            return length;
        }

    }

    public int readable() {
        return writeIndex - readIndex;
    }
    public void markReadIndex() {
        makeReadIndex = readIndex;
    }
    public void markWriteIndex() {
        makeWriteIndex = writeIndex;
    }
    public void resetReadIndex() {
        if (makeReadIndex != -1) {
            readIndex = makeReadIndex;
            makeReadIndex = -1;
        }
    }
    public void resetWriteIndex() {
        if (makeWriteIndex != -1) {
            writeIndex = makeWriteIndex;
            makeWriteIndex = -1;
        }
    }

    public byte[] toBytes() {
        int length = readable();

        if (length == 0) {
            return new byte[0];
        }

        byte[] bytes = new byte[length];

        System.arraycopy(values, readIndex, bytes, 0, length);
        return bytes;
    }

}
